using Microsoft.AspNetCore.Mvc.Filters; //ExceptionFilterAttribute
using Microsoft.AspNetCore.Mvc;         //ViewResult
using Microsoft.AspNetCore.Mvc.ModelBinding; //IModelMetadataProvider
using ShopForWeb.Dto.AjaxModels;
using ShopForWeb.Dto.ViewModels;
using ShopForWeb.UI.Extensions;

namespace ShopForWeb.UI.Filters
{
  /// <summary>
  /// 网站使用的全局异常 Filter
  /// </summary>
  public class GlobalExceptionFilter : Attribute, IExceptionFilter
  {

    private readonly ILogger<GlobalExceptionFilter>? _logger = null;
    private readonly IModelMetadataProvider _model;

    public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger, IModelMetadataProvider modelMetadataProvider)
    {
      _logger = logger;
      _model = modelMetadataProvider;
    }

    /// <summary>
    /// 捕获异常后处理
    /// </summary>
    /// <param name="context"></param>
    public void OnException(ExceptionContext context)
    {
      if (context.ExceptionHandled) return;
      if (this.IsAjaxRequest(context.HttpContext.Request))
      {
        //Ajax请求产生异常，回执使用Json格式1
        context.Result = new JsonResult(new ResponseAjaxModel()
        {
          Status = 1,
          Message = context.Exception.Message
        });
      }
      else
      {
        //View异常，跳转至专用的异常信息显示Action
        RedirectToActionResult? result = null;
        result = new RedirectToActionResult("Index", "Error", null);
        var type = context.Exception.GetType();
        //使用Session临时存储异常信息，中转给下一个Action
        context.HttpContext.Session.Set<ExceptionViewModel>("exception", new ExceptionViewModel()
        {
          FullName = context.Exception.GetType().FullName ?? "",
          Message = context.Exception.Message,
          StackTrace = context.Exception.StackTrace ?? ""
        });

        /* 网上Copy的原始版本，直接显示异常信息View，
        var result = new ViewResult
        {
          ViewName = @"~/Views/Error/Index.cshtml",
          ViewData = new ViewDataDictionary(_model, context.ModelState)
        };
        //传递数据
        result.ViewData.Add("FullName", context.Exception.FullName);
        result.ViewData.Add("Message", context.Exception.Message);
        result.ViewData.Add("StackTrace", context.Exception.StackTrace); 
        */
        context.Result = result;
      }
      context.ExceptionHandled = true; //异常已处理
    }

    /// <summary>
    /// 检测请求是否来自Ajax
    /// </summary>
    /// <param name="request">请求对象</param>
    /// <returns>bool</returns>
    private bool IsAjaxRequest(HttpRequest request)
    {
      string header = request.Headers["X-Requested-With"];
      return "XMLHttpRequest".Equals(header);
    }
  }
}
